#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//第14讲：深⼊理解指针(4)
//1. 回调函数是什么？
//回调函数就是⼀个通过函数指针调⽤的函数。
//说白了就是把A函数指针传给B函数，然后在B函数内部使用A函数,这个时候A就称为回调函数


//2. qsort 使⽤举例
//qsort -- 用来排序的(可以排序任意类型数据)
//库函数，直接可以用来排序数据，底层使用的是快速排序的方式

//使用qsort排序整型数组:
//void qsort(void* base,								//元素首地址
//			size_t num,									//数组元素个数(用sizeof求)
//			size_t size,								//一个元素的大小（用sizeof求）
//			int (*compar)(const void*, const void*));   //指针（用来决定对哪种类型的大小判断）

//int cmp_int(const void*p1, const void*p2)//由于指针类型是void*，所以无法解引用，指针也不能加减整数，因为不知道一次访问几个字节
//{										 //不过既然我们已经知道了要对int类型的数据比大小，我们可以先强制类型转换为int*类型，再对其解引用
//	return *(int*)p1 - *(int*)p2;//p1大于p2的时候返回正数
//}								 //p1等于p2的时候返回0
//								 //p1小于p2的时候返回负数
//int main()
//{
//	int arr[10] = { 2,5,1,0,7,4,3,6,8,9 };
//	size_t sz = sizeof(arr) / sizeof(arr[0]);
//	qsort(arr, sz, sizeof(arr[0]), cmp_int);
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}


//使用qsort排序结构体数据:
//这里的两个结构体元素怎么比大小？
//struct Stu
//{
//	char name[20];
//	int age;
//};

//1.按照名字比较 -- 字符串比较 -- strcmp
//int cmp_name(const void*p1, const void*p2)//如果要比较字符大小的话，那就先强制转化为struct Stu*类型,再去访问name成员
//{										  //用指针访问结构体成员: 指针->成员名
//	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
//}

//2.按照年龄比较 -- 整型比较
//int cmp_age(const void* p1, const void* p2)
//{										  
//	return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
//}
//
//int main()
//{
//	struct Stu arr[3] = { {"zhangsan",30},{"lisi",20},{"wangwu",18} };
//	size_t sz = sizeof(arr) / sizeof(arr[0]);
//	qsort(arr,sz,sizeof(arr[0]),cmp_name);//按照姓名排序
//	qsort(arr, sz, sizeof(arr[0]), cmp_age);//按照年龄排序
//
//	return 0;
//}


//我们来模仿qsort来实现一个冒泡排序的函数
//这个函数可以排序任意类型的数据
//int cmp_char(const void* p1, const void* p2)//这是我们自己写的，假设我们想要排序字符数组
//{
//	return strcmp((char*)p1,(char*)p2);
//}
//
//int cmp_int(const void* p1, const void* p2)//排序整型数组
//{
//	return *(int*)p1 - *(int*)p2;
//}
//
//void Swap(char* buf1, char* buf2, size_t width)
//{
//	int i = 0;
//	for (i = 0; i < width; i++)
//	{
//		char temp = *buf1;
//		*buf1 = *buf2;
//		*buf2 = temp;
//		buf1++;
//		buf2++;
//	}
//}
//void bubble_sort(void* base, size_t sz,size_t width,int (*cmp)(const void*,const void*))
//{																	//void* base 获取数组首地址，不知道类型但总要知道地址在哪吧
//	int i = 0;														//size_t sz  总要知道数组有多少个元素吧
//	for (i = 0; i < sz - 1; i++)									//size_t width 总要知道一个元素多宽吧（元素的大小）
//	{																//int (*cmp)(const void*,const void*) 函数指针，比较方法
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)//升序
//			{
//				Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
//			}
//		}
//	}
//}
//int main()
//{
//	char arr1[] = "ejbgfacd";
//	int arr2[] = { 6,3,7,9,2,5,7,8,2,1,0,4 };
//	size_t sz1 = sizeof(arr1) / sizeof(arr1[0]);
//	size_t sz2 = sizeof(arr2) / sizeof(arr2[0]);
//	bubble_sort(arr1, sz1, sizeof(arr1[0]), cmp_char);//排序字符串类型的数据
//	bubble_sort(arr2, sz2, sizeof(arr2[0]), cmp_int);//排序整型类型的数据
//	for (int i = 0; i < sz1; i++)
//	{
//		printf("%c ", arr1[i]);//打印排序好的字符串数组
//	}
//	printf("\n");
//	for (int i = 0; i < sz2; i++)
//	{
//		printf("%d ", arr2[i]);//打印排序好的整型数组
//	}
//
//	return 0;
//}

//int main()
//{
//	char arr[] = "abcdef";
//	char* p0 = arr;
//	char* p1 = arr + 1;
//	int ret = strcmp(p1,p0);  //strcmp里面要求是 const char*类型的数据，也就是指针(strcmp不能比较字符)
//	printf("%d", ret);		  //p1和p0比较就是 bcdef 和 abcdef比较，由于第一个字符b>a 所以返回1
//	return 0;
//}
